#region File Description
//-----------------------------------------------------------------------------
// MainForm.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.Text;
using System.Collections.Generic;
using Stonecode.Solar.ParticleEngine;
using Stonecode.Solar.ParticleEngine.Collections;
using Stonecode.Solar.ParticleEngine.Emitters;
using Stonecode.Solar.ParticleEffectEditor;
using Stonecode.Solar.ParticleEffectEditor.Serialization;

#endregion

namespace Stonecode.Solar.ParticleEffectEditor
{
    /// <summary>
    /// Custom form provides the main user interface for the program.
    /// In this sample we used the designer to fill the entire form with a
    /// ModelViewerControl, except for the menu bar which provides the
    /// "File / Open..." option.
    /// </summary>
    public partial class MainForm : Form
    {
        ContentBuilder contentBuilder;
        ContentManager contentManager;

        EmitterCollection effectCollection; // = new EmitterCollection();
        

        Effect particleEffect;
        Texture2D defaultTexture;
        //List<Texture2D> TextureList = new List<Texture2D>();
        NamedTexture2DCollection TextureList;
        ImageList textureIconList;

        // this helps bridge the settins so that we can use custom UIType Editors
        Win_EmitterSettings localEmitterSettings = new Win_EmitterSettings();

        int selectedEmitter = -1;

        string filePath = "";

        bool isLoaded = false;

        // EmitterTypeSettings
        Win_CircleEmitterTypeSettings circleEmitterSettings = new Win_CircleEmitterTypeSettings();
        Win_RectangleEmitterTypeSettings rectangleEmitterSettings = new Win_RectangleEmitterTypeSettings();
        Win_LineEmitterTypeSettings lineEmitterSettings = new Win_LineEmitterTypeSettings();


        /// <summary>
        /// Constructs the main form.
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            contentBuilder = new ContentBuilder();

            contentManager = new ContentManager(modelViewerControl.Services,
                                                contentBuilder.OutputDirectory);
            contentManager.RootDirectory = Application.StartupPath + "\\Content";

            //contentManager = new ContentManager(modelViewerControl.Services, Application.StartupPath + "\\Content");

            textureIconList = new ImageList();
            textureIconList.ImageSize = new System.Drawing.Size(128, 128);
            /// Automatically bring up the "Load Model" dialog when we are first shown.
            //this.Shown += OpenMenuClicked;

            //modelViewerControl.SettingsEffect = new BasicEffect(modelViewerControl.GraphicsDevice, null);
            propertyGrid1.SelectedObject = null;
            modelViewerControl.MouseWheel += new MouseEventHandler(modelViewerControl_MouseWheel);
            modelViewerControl.MouseDown += new MouseEventHandler(modelViewerControl_MouseDown);
            //modelViewerControl.MouseUp += new MouseEventHandler(modelViewerControl_MouseUp);
            effectCollection = new EmitterCollection();
            modelViewerControl.EmitterCollection = effectCollection;

            textureIconList.ColorDepth = ColorDepth.Depth32Bit;
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            particleEffect = contentManager.Load<Effect>("ParticleEffect");
            
            TextureList = new NamedTexture2DCollection();
            //TextureList.Add(new NamedTexture2D("particle", contentManager.RootDirectory + "\\..\\Textures\\particle.png", contentManager.Load<Texture2D>("particle")));
            //textureIconList.Images.Add(System.Drawing.Image.FromFile("Textures\\particle.png"));
            
            LoadTextures(Application.StartupPath + "\\Textures");
            //defaultTexture = TextureList[0].Texture;
            TextureList.GetTextureByName("particle", true, out defaultTexture);

            this.propertyGrid1.SelectedObject = null; // this.modelViewerControl;
            applyBlendTemplateToolStripMenuItem.Enabled = false;
            SetCameraPosition();
            isLoaded = true;
        }

        void modelViewerControl_MouseUp(object sender, MouseEventArgs e)
        {
            modelViewerControl.leftButtonIsDown = false;

            if (!modelViewerControl.AutoTrigger)
                effectCollection.SetAlive(false);
        }

        


        /// <summary>
        /// Event handler for the Exit menu option.
        /// </summary>
        void ExitMenuClicked(object sender, EventArgs e)
        {
            Close();
        }


        /// <summary>
        /// Event handler for the Open menu option.
        /// </summary>
        void OpenMenuClicked(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog
            {
                Filter = "Effect Files (*.xml) | *.xml",
                DefaultExt = ".xml"
            };

            if (ofd.ShowDialog() != DialogResult.OK)
                return;

            string path = ofd.FileName;

            List<OutputSettings> settings;
            FileHandler.ReadFile(path, out settings);
            if (settings == null)
                return;

            emitterList.Items.Clear();
            if (effectCollection == null)
                effectCollection = new EmitterCollection();
            else
                effectCollection.Clear();

            foreach (OutputSettings os in settings)
            {
                EmitterSettings s;
                EmitterTypeSettings ets;
                os.ConvertToEmitterSettings(out s, out ets);

                Texture2D tex = null;
                TextureList.GetTextureByName(s.TextureName, true, out tex);
                if (tex == null)
                {
                    // load the texture into the library
                    LoadTextureIntoLibrary(os.TextureFullName);
                }

                int index = effectCollection.Count;
                CheckState cs = new CheckState();
                if (os.Enabled)
                    cs = CheckState.Checked;
                else
                    cs = CheckState.Unchecked;
                switch (ets.EmitterType)
                {
                    case EmitterType.Circle: AddCircleEmitter(s, os.EmitterName, (CircleEmitterTypeSettings)ets, tex); break;
                    case EmitterType.Line: AddLineEmitter(s, os.EmitterName, (LineEmitterTypeSettings)ets, tex); break;
                    case EmitterType.Point: AddPointEmitter(s, os.EmitterName, (PointEmitterTypeSettings)ets, tex); break;
                    case EmitterType.Rectangle: AddRectangleEmitter(s, os.EmitterName, (RectangleEmitterTypeSettings)ets, tex); break;
                }

                effectCollection[index].Enabled = os.Enabled;
                emitterList.SetItemCheckState(index, cs);
            }

            modelViewerControl.EmitterCollection = effectCollection;
            emitterList.SelectedIndex = 0;
        }


        

        private void LoadTextures(string path)
        {
            if (!System.IO.Directory.Exists(path))
                System.IO.Directory.CreateDirectory(path);

            DirectoryInfo di = new DirectoryInfo(path);
            List<ListViewItem> items = new List<ListViewItem>();
            List<string> names = new List<string>();
            contentBuilder.Clear();
            bool itemsToBuild = false;

            List<string> filesToCopy = new List<string>();
            List<string> sourceImagePaths = new List<string>();
            foreach(FileInfo fi in di.GetFiles())
            {
                if (MatchTextureExtension(fi.Extension))
                {
                    string name = fi.Name.Replace(fi.Extension, "");

                    if (!File.Exists(contentManager.RootDirectory + "\\" + name + ".xnb"))
                    {
                        contentBuilder.Add(fi.FullName, name, null, null);
                        itemsToBuild = true;
                        filesToCopy.Add(contentBuilder.OutputDirectory + "\\" + name + ".xnb");
                    }
                    names.Add(name);
                    System.Drawing.Image image = System.Drawing.Image.FromFile(fi.FullName);
                    sourceImagePaths.Add(fi.FullName);
                    textureIconList.Images.Add(image);
                }
            }

            if (itemsToBuild)
            {
                contentBuilder.Build();
                foreach (string s in filesToCopy)
                {
                    string name = s.Substring(s.LastIndexOf('\\'));
                    if (!File.Exists(contentManager.RootDirectory + name))
                        System.IO.File.Copy(s, contentManager.RootDirectory + name);
                }
            }
            textureListView.SmallImageList = textureIconList;
            textureListView.LargeImageList = textureIconList;
            
            for(int i=0; i < names.Count; i++) // (string name in names)
            {
                TextureList.Add(new NamedTexture2D(names[i], sourceImagePaths[i], contentManager.Load<Texture2D>(names[i])));
                
                int index = items.Count;
                items.Add(new ListViewItem());
                
                items[index].ImageIndex = index;
                items[index].Text = names[i];
            }
            

            
            for (int i = 0; i < items.Count; i++)
            {
                textureListView.Items.Add(items[i]);
            }
        }

        private bool MatchTextureExtension(string ext)
        {
            switch (ext.ToLower())
            {
                case ".tga": break;
                case ".jpg": break;
                case ".bmp": break;
                case ".png": break;
                default: return false;
            }
            return true;
        }
        
        private string NewV3ToString(Vector3 v)
        {
            return "new Vector3(" + v.X.ToString() + "f, " + v.Y.ToString() + "f, " + v.Z.ToString() + "f)";
        }

        private void renderBackColorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorDialog cd = new ColorDialog();
            
            if (cd.ShowDialog() == DialogResult.OK)
            {
                System.Drawing.Color res = cd.Color;
                Color c = new Color(res.R, res.G, res.B);
                modelViewerControl.BackColor = c;
            }
        }

        private void modelViewerControl_MouseDown(object sender, MouseEventArgs e)
        {
            //modelViewerControl.Select();
            //if (e.Button == MouseButtons.Left)
            //    modelViewerControl.RotatingModelWithMouse = true;
            //else if (e.Button == MouseButtons.Right)
            //    modelViewerControl.RotatingCameraWithMouse = true;
            //else if (e.Button == MouseButtons.Middle)
            //    modelViewerControl.RotatingLookatWithMouse = true;
            modelViewerControl.leftButtonIsDown = true;
            if (!modelViewerControl.AutoTrigger)
                effectCollection.SetAlive(true);
        }

        void modelViewerControl_MouseWheel(object sender, MouseEventArgs e)
        {
            if (modelViewerControl.Camera != null)
            {
                modelViewerControl.Camera.ZoomCamera(e.Delta);
                
            }
        }

        private void CameraDataChanged(object sender)
        {
            if (propertyGrid1.SelectedObject == modelViewerControl.Camera)
            {
                propertyGrid1.SelectedObject = modelViewerControl.Camera;
            }
        }

        private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            localEmitterSettings.GetEmitterSettings(effectCollection[selectedEmitter].ParticleSystem.Settings);
            effectCollection[selectedEmitter].ParticleSystem.ApplyEffectSettings();
            effectCollection[selectedEmitter].ParticleSystem.Settings.ApplyBlendOptions();
        }

        private void propertyGrid2_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            switch (effectCollection[selectedEmitter].EmitterType)
            {
                case EmitterType.Circle:
                    {
                        circleEmitterSettings.GetEmitterTypeSettings(((CircleEmitter)effectCollection[selectedEmitter]).EmitterTypeSettings);
                        break;
                    }
                case EmitterType.Line:
                    {
                        lineEmitterSettings.GetEmitterTypeSettings(((LineEmitter)effectCollection[selectedEmitter]).EmitterTypeSettings);
                        break;
                    }
                case EmitterType.Rectangle:
                    {
                        rectangleEmitterSettings.GetEmitterTypeSettings(((RectangleEmitter)effectCollection[selectedEmitter]).EmitterTypeSettings);
                        break;
                    }
            }
        }
        private void loadEffectSettingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //OpenFileDialog ofd = new OpenFileDialog
            //{
            //    Title = "Load Effect Settings",
            //    AddExtension = true,
            //    CheckFileExists = true,
            //    CheckPathExists = true,
            //    DefaultExt = ".txt",
            //    Filter = "Text File (*.txt)|*.txt|All Files|*",
            //};
            //if (ofd.ShowDialog() == DialogResult.OK)
            //{
            //    LoadSettingsFile(ofd.FileName);
            //}
        }

        private void LoadSettingsFile(string file)
        {
            
        }

        

        private Vector3 ParseVector(string s)
        {
            Vector3 v = new Vector3();
            string val = s.Replace("(", "");
            val = val.Replace(")", "");
            string[] split = val.Split(',');
            if (split == null || split.Length == 0)
                return v;

            v.X = float.Parse(split[0]);
            v.Y = float.Parse(split[1]);
            v.Z = float.Parse(split[2]);

            return v;
        }
        private string FormatVector3(Vector3 v)
        {
            string s = "(" + v.X + "," + v.Y + "," + v.Z + ")";
            return s;
        }

        

        #region File Menu Button Handlers

        

       
        #endregion

        private void btnNewEmitter_Click(object sender, EventArgs e)
        {
            newEmitterForm form = new newEmitterForm();
            form.myParent = this;
            form.ShowDialog();
            if (!form.canceled)
            {
                EmitterSettings ps = new EmitterSettings(form.ParticleCount);
                ps.ParticlesPerSecond = form.ParticleRate;
                ps.TextureName = "Particle";
                ps.Enabled = true;
                AddNewEmitter(ps, form.EmitterType, form.EmitterName);
                emitterList.SelectedIndex = emitterList.Items.Count - 1;
            }
            
            this.Activate();
            form.Dispose();
            //this.BringToFront();
            
        }

        private void AddNewEmitter(EmitterSettings ps, EmitterType type, string name)
        {
            switch (type)
            {
                case EmitterType.Circle: AddCircleEmitter(ps, name); break;
                case EmitterType.Line: AddLineEmitter(ps, name); break;
                case EmitterType.Point: AddPointEmitter(ps, name); break;
                case EmitterType.Rectangle: AddRectangleEmitter(ps, name); break;
            }

            effectCollection.SetAlive(modelViewerControl.AutoTrigger);
            //effectCollection[effectCollection.Count - 1].IsAlive = false;
        }

        private void emitterList_SelectedIndexChanged(object sender, EventArgs e)
        {
            //CircleEmitterTypeSettings circleEmitterSettings;
            //RectangleEmitterTypeSettings rectangleEmitterSettings;
            //LineEmitterTypeSettings lineEmitterSettings;
            selectedEmitter = emitterList.SelectedIndex;
            if (selectedEmitter != -1)
            {
                switch (effectCollection[selectedEmitter].EmitterType)
                {
                    case EmitterType.Circle:
                        {
                            circleEmitterSettings.SetEmitterTypeSettings(((CircleEmitter)effectCollection[selectedEmitter]).EmitterTypeSettings);
                            propertyGrid2.SelectedObject = circleEmitterSettings;
                            break;
                        }
                    case EmitterType.Line:
                        {
                            lineEmitterSettings.SetEmitterTypeSettings(((LineEmitter)effectCollection[selectedEmitter]).EmitterTypeSettings);
                            propertyGrid2.SelectedObject = lineEmitterSettings;
                            break;
                        }
                    case EmitterType.Point: propertyGrid2.SelectedObject = ((PointEmitter)effectCollection[selectedEmitter]).EmitterTypeSettings; break;
                    case EmitterType.Rectangle:
                        {
                            rectangleEmitterSettings.SetEmitterTypeSettings(((RectangleEmitter)effectCollection[selectedEmitter]).EmitterTypeSettings);
                            propertyGrid2.SelectedObject = rectangleEmitterSettings; 
                            break;
                        }
                }

                localEmitterSettings.SetFromEmitterSettings(effectCollection[selectedEmitter].ParticleSystem.Settings);
                propertyGrid1.SelectedObject = localEmitterSettings;
                applyBlendTemplateToolStripMenuItem.Enabled = true;
            }
            else
            {
                propertyGrid1.SelectedObject = null;
                propertyGrid2.SelectedObject = null;
                applyBlendTemplateToolStripMenuItem.Enabled = false;
            }
        }

        private void deleteTextureToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (textureListView.SelectedItems == null || textureListView.SelectedItems.Count == 0)
                return;


            DeleteTexture(textureListView.SelectedItems[0].Text);
            
        }

        private void DeleteTexture(string name)
        {
            if (name.ToLower() == "particle")
            {
                MessageBox.Show("Cannot delete the default Particle texture... This would be bad...");
                return;
            }

            // Reset the default texture
            TextureList.GetTextureByName("particle", true, out defaultTexture);

            // Check to see if there are any emitters that have this texture
            Texture2D tex; TextureList.GetTextureByName(name, true, out tex);
            bool replaceTexture = false;
            foreach (Emitter em in effectCollection)
            {
                if (em.ParticleSystem.Texture == tex)
                {
                    if (MessageBox.Show("This texture currently applied to an emitter. Deleting it will reset that emitter's Texture to the default particle",
                        "Replace texture on emitter(s)?", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No)
                    {
                        return;
                    }
                    else
                        replaceTexture = true;
                }
            }

            if (replaceTexture)
            {
                foreach (Emitter em in effectCollection)
                {
                    if (em.ParticleSystem.Texture == tex)
                    {
                        em.ParticleSystem.SetTexture(defaultTexture);
                        em.ParticleSystem.ApplyEffectSettings();
                    }
                }
            }

            try
            {
                System.IO.File.Delete(String.Format("{0}\\{1}.xmb", contentManager.RootDirectory, name));
                foreach (string file in System.IO.Directory.GetFiles(contentManager.RootDirectory + "\\..\\Textures"))
                {
                    System.IO.FileInfo fi = new FileInfo(file);
                    if (fi.Name.Replace(fi.Extension, "").ToLower() == name.ToLower())
                        fi.Delete();
                }

            }
            catch(System.IO.IOException ex)
            {
                txtErrors.Text += String.Format("{0}{1}", Environment.NewLine, ex.Message);
            }

            int index = TextureList.RemoveTextureByName(name);
            if (index != -1)
                textureIconList.Images.RemoveAt(index);

            textureListView.Items.RemoveAt(textureListView.SelectedIndices[0]);
            textureListView.Update();

        }

        private void applyTextureToCureentEmitterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetSelectedTextureOnEmitter();
        }

        private void textureListView_DoubleClick(object sender, EventArgs e)
        {
            SetSelectedTextureOnEmitter();
        }

        private void SetSelectedTextureOnEmitter()
        {
            if (textureListView.SelectedItems == null || textureListView.SelectedItems.Count == 0)
                return;

            //int index = textureListView.SelectedItems[0].Index;

            if (selectedEmitter != -1)
            {
                Texture2D tex; TextureList.GetTextureByName(textureListView.SelectedItems[0].Text, false, out tex);
                effectCollection[selectedEmitter].ParticleSystem.SetTexture(tex);
                effectCollection[selectedEmitter].ParticleSystem.Settings.TextureName = textureListView.SelectedItems[0].Text;
            }
        }

        private void texturesContextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (textureListView.SelectedItems == null || textureListView.SelectedItems.Count == 0)
            {
                texturesContextMenu.Items[0].Enabled = false;
                texturesContextMenu.Items[1].Enabled = false;
                //applyTextureToCureentEmitterToolStripMenuItem.Enabled = false;
                //deleteTextureToolStripMenuItem.Enabled = false;
            }
            else
            {
                texturesContextMenu.Items[0].Enabled = true;
                texturesContextMenu.Items[1].Enabled = true;
                //applyTextureToCureentEmitterToolStripMenuItem.Enabled = false;
                //deleteTextureToolStripMenuItem.Enabled = false;
            }
        }

        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog
            {
                Title = "Load Texture",
                AddExtension = true,
                CheckFileExists = true,
                CheckPathExists = true,
                DefaultExt = ".txt",
                Filter = "Texture Files (*.png;*.jpg;*.bmp)|*.png;*.jpg;*.bmp|" +
                                        "Portable Graphics Files (*.png)|*.png|" +
                                        "JPEG Files (*.jpg)|*.jpg|" +
                                        "Bitmap Files (*.jpg)|*.jpg|" +
                                        "All Files (*.*)|*.*",
                
            };
            
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                LoadTextureIntoLibrary(ofd.FileName);
                
            }

            ofd.Dispose();
        }

        private void LoadTextureIntoLibrary(string path)
        {
            FileInfo fi = new FileInfo(path);
            string name = fi.Name.Replace(fi.Extension, "");

            // check if this file already exists...
            if (File.Exists(contentManager.RootDirectory + "\\" + name + ".xnb"))
            {
                if (MessageBox.Show("This file already exists. Are you sure you want to overwrite?", "Overwrite File?", MessageBoxButtons.YesNo) == DialogResult.No)
                {
                    fi = null;
                    return;
                }
            }

            // Copy the texture to the cache for next load
            File.Copy(fi.FullName, contentManager.RootDirectory + "\\..\\Textures\\" + fi.Name, true);
            contentBuilder.Clear();

            contentBuilder.Add(path, name, null, null);
            contentBuilder.Build();
            if (!File.Exists(contentManager.RootDirectory + "\\" + name + ".xnb"))
                File.Copy(contentBuilder.OutputDirectory + "\\" + name + ".xnb",
                    contentManager.RootDirectory + "\\" + name + ".xnb");
            textureIconList.Images.Add(System.Drawing.Image.FromFile(path));
            ListViewItem lvi = new ListViewItem();

            int index = TextureList.Count;
            TextureList.Add(new NamedTexture2D(name, contentManager.RootDirectory + "\\..\\Textures\\" + fi.Name, contentManager.Load<Texture2D>(name)));

            lvi.ImageIndex = index;
            lvi.Text = name;
            textureListView.Items.Add(lvi);
        }

        private void btnDeleteEmitter_Click(object sender, EventArgs e)
        {
            if (selectedEmitter == -1)
                return;

            if (MessageBox.Show("Are you sure you want to delete this emitter?", "Delete Emitter?", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
            {
                int index = selectedEmitter;
                emitterList.Items.RemoveAt(index);
                effectCollection.RemoveAt(index);
                if (index > emitterList.Items.Count - 1)
                    emitterList.SelectedIndex = emitterList.Items.Count - 1;
                else
                    emitterList.SelectedIndex = index;
            }
        }

        private void modelViewerControl_SizeChanged(object sender, EventArgs e)
        {
            
            UpdateView();
        }

        private void splitContainer2_SplitterMoved(object sender, SplitterEventArgs e)
        {
            UpdateView();
        }

        private void UpdateView()
        {
            // hold off on this if we haven't fully loaded yet
            if (!isLoaded)
                return;

            try
            {
                if (modelViewerControl.GraphicsDevice == null)
                    return;
            }
            catch (NullReferenceException ex) { return; }

            //modelViewerControl.ResetCamera();
            SetCameraPosition();

            for (int i = 0; i < effectCollection.Count; i++)
            {
                //effectCollection[i].ParticleSystem.ClearParticles();
                effectCollection[i].ParticleSystem.SetCamera(modelViewerControl.Camera.ViewMatrix, modelViewerControl.Camera.ProjectionMatrix);
            }
        }

        private void numBoxCameraX_ValueChanged(object sender, EventArgs e)
        {
            SetCameraPosition();
        }

        private void numBoxCameraY_ValueChanged(object sender, EventArgs e)
        {
            SetCameraPosition();
        }

        private void numBoxCameraZ_ValueChanged(object sender, EventArgs e)
        {
            SetCameraPosition();
        }

        private void numBoxFOV_ValueChanged(object sender, EventArgs e)
        {
            SetCameraPosition();
        }

        private void SetCameraPosition()
        {
            float x = (float)numBoxCameraX.Value;
            float y = (float)numBoxCameraY.Value;
            float z = (float)numBoxCameraZ.Value;
            float near = (float)numBoxClipNear.Value;
            float far = (float)numBoxClipFar.Value;
            float fov = (float)numBoxFOV.Value;

            //modelViewerControl.Camera.Position = new Vector3(x, y, z);

            modelViewerControl.ResetCamera(new Vector3(x,y,z), near, far, fov, true);

            for (int i = 0; i < effectCollection.Count; i++)
            {
                effectCollection[i].ParticleSystem.SetCamera(modelViewerControl.Camera.ViewMatrix, modelViewerControl.Camera.ProjectionMatrix);
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (filePath == "")
                SaveAs();
            else
                SaveFile(filePath);
        }

        private void emitterList_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            int index = emitterList.SelectedIndex;
            if (index != -1)
            {
                effectCollection[index].Enabled = (e.NewValue == CheckState.Checked);
                effectCollection[index].ParticleSystem.Settings.Enabled = effectCollection[index].Enabled;

            }
        }

        private void AddRectangleEmitter(EmitterSettings ps, string name)
        {

            RectangleF rec = new RectangleF(Vector2.Zero, 0, Vector2.One * 10f);
            effectCollection.Add(new RectangleEmitter(modelViewerControl.GraphicsDevice, particleEffect,
                ps, defaultTexture, ps.ParticlesPerSecond, rec, 0, modelViewerControl.Camera.ViewMatrix, modelViewerControl.Camera.ProjectionMatrix));

            effectCollection[effectCollection.Count - 1].EmitterName = name;

            emitterList.Items.Add(name, true);

        }

        private void AddRectangleEmitter(EmitterSettings ps, string name, RectangleEmitterTypeSettings ets, Texture2D tex)
        {

            RectangleF rec = new RectangleF(Vector2.Zero, 0, new Vector2(ets.Rectangle.Width, ets.Rectangle.Height));

            effectCollection.Add(new RectangleEmitter(modelViewerControl.GraphicsDevice, particleEffect,
                ps, tex, ps.ParticlesPerSecond, rec, 0, modelViewerControl.Camera.ViewMatrix, modelViewerControl.Camera.ProjectionMatrix));

            effectCollection[effectCollection.Count - 1].EmitterName = name;

            emitterList.Items.Add(name, true);

        }

        private void AddPointEmitter(EmitterSettings ps, string name)
        {
            effectCollection.Add(new PointEmitter(modelViewerControl.GraphicsDevice, particleEffect,
                ps, defaultTexture, ps.ParticlesPerSecond, Vector3.Zero, modelViewerControl.Camera.ViewMatrix, modelViewerControl.Camera.ProjectionMatrix));
            effectCollection[effectCollection.Count - 1].EmitterName = name;
            emitterList.Items.Add(name, true);
        }

        private void AddPointEmitter(EmitterSettings ps, string name, PointEmitterTypeSettings ets, Texture2D tex)
        {
            effectCollection.Add(new PointEmitter(modelViewerControl.GraphicsDevice, particleEffect,
                ps, ets, tex, ps.ParticlesPerSecond, Vector3.Zero, modelViewerControl.Camera.ViewMatrix, modelViewerControl.Camera.ProjectionMatrix));
            effectCollection[effectCollection.Count - 1].EmitterName = name;
            emitterList.Items.Add(name, true);
        }

        private void AddLineEmitter(EmitterSettings ps, string name)
        {
            effectCollection.Add(new LineEmitter(modelViewerControl.GraphicsDevice, particleEffect, ps,
                defaultTexture, ps.ParticlesPerSecond, Vector3.Zero, 10f, 0, modelViewerControl.Camera.ViewMatrix, modelViewerControl.Camera.ProjectionMatrix));
            effectCollection[effectCollection.Count - 1].EmitterName = name;
            emitterList.Items.Add(name, true);
        }

        private void AddLineEmitter(EmitterSettings ps, string name, LineEmitterTypeSettings ets, Texture2D tex)
        {
            effectCollection.Add(new LineEmitter(modelViewerControl.GraphicsDevice, particleEffect, ps,
                tex, ps.ParticlesPerSecond, Vector3.Zero, ets.LineLength, ets.Rotation, modelViewerControl.Camera.ViewMatrix, modelViewerControl.Camera.ProjectionMatrix));
            effectCollection[effectCollection.Count - 1].EmitterName = name;
            emitterList.Items.Add(name, true);
        }

        private void AddCircleEmitter(EmitterSettings ps, string name)
        {
            effectCollection.Add(new CircleEmitter(modelViewerControl.GraphicsDevice, particleEffect, ps,
                defaultTexture, ps.ParticlesPerSecond, Vector3.Zero, 20f, modelViewerControl.Camera.ViewMatrix, modelViewerControl.Camera.ProjectionMatrix));
            effectCollection[effectCollection.Count - 1].EmitterName = name;
            emitterList.Items.Add(name, true);
        }

        private void AddCircleEmitter(EmitterSettings ps, string name, CircleEmitterTypeSettings ets, Texture2D tex)
        {
            effectCollection.Add(new CircleEmitter(modelViewerControl.GraphicsDevice, particleEffect, ps,
                tex, ps.ParticlesPerSecond, Vector3.Zero, ets.Radius, modelViewerControl.Camera.ViewMatrix, modelViewerControl.Camera.ProjectionMatrix));
            effectCollection[effectCollection.Count - 1].EmitterName = name;
            ((CircleEmitter)effectCollection[effectCollection.Count - 1]).EmitterTypeSettings.StartAngle = ets.StartAngle;
            ((CircleEmitter)effectCollection[effectCollection.Count - 1]).EmitterTypeSettings.EndAngle = ets.EndAngle;
            emitterList.Items.Add(name, true);
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveAs();
        }

        private void SaveAs()
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.OverwritePrompt = true;
            sfd.DefaultExt = ".xml";
            sfd.AddExtension = true;
            sfd.Filter = "Effect Files (*.xml) | *.xml";
            string path = "";
            if (sfd.ShowDialog() != DialogResult.OK)
                return;

            path = sfd.FileName;
            SaveFile(path);
        }
        private void SaveFile(string path)
        {
            FileHandler.WriteFile(path, effectCollection);
        }

        #region Old Way
        //private void SaveFile(string path)
        //{
        //    List<OutputSettings> settings = new List<OutputSettings>();
        //    foreach (Emitter emitter in effectCollection)
        //    {
        //        OutputSettings s = new OutputSettings();
        //        EmitterTypeSettings ets = new EmitterTypeSettings(EmitterType.Point);
        //        switch (emitter.EmitterType)
        //        {
        //            case EmitterType.Circle: ets = ((CircleEmitter)emitter).EmitterTypeSettings; break;
        //            case EmitterType.Line: ets = ((LineEmitter)emitter).EmitterTypeSettings; break;
        //            case EmitterType.Point: ets = ((PointEmitter)emitter).EmitterTypeSettings; break;
        //            case EmitterType.Rectangle: ets = ((RectangleEmitter)emitter).EmitterTypeSettings; break;
        //        }

        //        s.AssignSettings(emitter.ParticleSystem.Settings, ets, emitter);
        //        s.TextureFullName = TextureList[TextureList.GetIndexByName(s.TextureName)].TextureSourcePath;
        //        settings.Add(s);

        //        // copy the texture
        //        string imageSavePath = path.Remove(path.LastIndexOf("\\") + 1);
        //        imageSavePath += s.TextureFullName.Remove(0, s.TextureFullName.LastIndexOf("\\") + 1);
        //        if (!File.Exists(imageSavePath))
        //            File.Copy(s.TextureFullName, imageSavePath);
        //    }

        //    FileHandler.WriteFile(path, settings);

             
        //}
        #endregion

        private void numBoxClipFar_ValueChanged(object sender, EventArgs e)
        {
            SetCameraPosition();
        }

        private void numBoxClipNear_ValueChanged(object sender, EventArgs e)
        {
            SetCameraPosition();
        }

        private void numBoxAspect_ValueChanged(object sender, EventArgs e)
        {
            SetCameraPosition();
        }

        private void resetAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (effectCollection != null)
            {
                if (MessageBox.Show("Are you sure you want to start over and lose the current project?", "Reset?", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2) == DialogResult.No)
                {
                    return;
                }
            }

            emitterList.Items.Clear();
            filePath = "";

            if (effectCollection == null)
            {
                effectCollection = new EmitterCollection();
                modelViewerControl.EmitterCollection = effectCollection;
            }

            effectCollection.Clear();
            propertyGrid1.SelectedObject = null;
            propertyGrid2.SelectedObject = null;
            applyBlendTemplateToolStripMenuItem.Enabled = false;
        }

        private void additiveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            effectCollection[selectedEmitter].ParticleSystem.Settings.SetKnownBlendOptions(KnownBlendOptions.Additive);
            emitterList_SelectedIndexChanged(sender, new EventArgs());
        }

        private void subtractiveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            effectCollection[selectedEmitter].ParticleSystem.Settings.SetKnownBlendOptions(KnownBlendOptions.Subtractive);
            emitterList_SelectedIndexChanged(sender, new EventArgs());
        }

        private void nonPremultipliedToolStripMenuItem_Click(object sender, EventArgs e)
        {
            effectCollection[selectedEmitter].ParticleSystem.Settings.SetKnownBlendOptions(KnownBlendOptions.NonPremultiplied);
            emitterList_SelectedIndexChanged(sender, new EventArgs());
        }

        private void alphaBlendToolStripMenuItem_Click(object sender, EventArgs e)
        {
            effectCollection[selectedEmitter].ParticleSystem.Settings.SetKnownBlendOptions(KnownBlendOptions.AlphaBlend);
            emitterList_SelectedIndexChanged(sender, new EventArgs());
        }

        private void opaqueToolStripMenuItem_Click(object sender, EventArgs e)
        {
            effectCollection[selectedEmitter].ParticleSystem.Settings.SetKnownBlendOptions(KnownBlendOptions.Opaque);
            emitterList_SelectedIndexChanged(sender, new EventArgs());
        }

        private void collectionMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
        {
            renameEmitterToolStripMenuItem.Enabled = (selectedEmitter != -1);
        }

        private void renameEmitterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string currentName = emitterList.Items[selectedEmitter].ToString();
            FrmChangeEmitterName fcen = new FrmChangeEmitterName(currentName);
            if (fcen.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                emitterList.Items[selectedEmitter] = fcen.EmitterName;

            fcen.Dispose();
            this.Activate();
        }

        private void RenameEmitter(string name, int index)
        {
            if (index < 0)
                return;

            emitterList.Items[index] = name;
            effectCollection[index].EmitterName = name;
            effectCollection[index].ParticleSystem.Settings.EmitterName = name;
        }

        private void btnMoveUp_Click(object sender, EventArgs e)
        {
            if (selectedEmitter <= 0)
                return;

            MoveItem(selectedEmitter, selectedEmitter - 1);
        }

        private void btnMoveDown_Click(object sender, EventArgs e)
        {
            if (selectedEmitter >= effectCollection.Count - 1 || selectedEmitter == -1)
                return;

            MoveItem(selectedEmitter, selectedEmitter + 1);
        }

        private void MoveItem(int indexFrom, int indexTo)
        {
            Emitter[] emitters = new Emitter[2];
            emitters[0] = effectCollection[indexFrom];
            emitters[1] = effectCollection[indexTo];
            effectCollection[indexFrom] = emitters[1];
            effectCollection[indexTo] = emitters[0];

            emitterList.Items.Clear();

            foreach (Emitter e in effectCollection)
            {
                emitterList.Items.Add(e.EmitterName, e.Enabled);
            }

            emitterList.SelectedIndex = indexTo;
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmAbout about = new FrmAbout();
            about.ShowDialog();
            about.Dispose();
        }

        private void autoTriggerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            bool val = !autoTriggerToolStripMenuItem.Checked;
            autoTriggerToolStripMenuItem.Checked = val;
            this.modelViewerControl.AutoTrigger = val;
            
            //effectCollection.SetAutoGenerate(val);
            effectCollection.SetAlive(val);
        }

        private void showCollectionCenterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            bool newVal = !showCollectionCenterToolStripMenuItem.Checked;
            showCollectionCenterToolStripMenuItem.Checked = newVal;
            modelViewerControl.ShowEmitterLocation = newVal;
        }

        private void showEmitterOffsetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            bool newVal = !showEmitterOffsetToolStripMenuItem.Checked;
            showEmitterOffsetToolStripMenuItem.Checked = newVal;
            modelViewerControl.ShowOffsets = newVal;
        }

        private void animateGravityToolStripMenuItem_Click(object sender, EventArgs e)
        {
            bool newVal = !animateGravityToolStripMenuItem.Checked;
            animateGravityToolStripMenuItem.Checked = newVal;
            modelViewerControl.AnimateRotatingGravity = newVal;

        }

        

        

        

        

        

        
        
    }
}
